#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "gd32f30x.h"

static void GpioInit(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);

	gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
}

static void CanInit(void)
{
	rcu_periph_clock_enable(RCU_CAN0);
	
	can_parameter_struct        canInitPara;                  // CAN初始化参数
	can_filter_parameter_struct canFilterPara;                // CAN过滤器初始化参数
	can_struct_para_init(CAN_INIT_STRUCT, &canInitPara);      // CAN参数设为默认值
	can_struct_para_init(CAN_FILTER_STRUCT, &canFilterPara);  // 过滤器参数设为默认值
	
	/* 初始化CAN0寄存器 */
	can_deinit(CAN0);
	
	canInitPara.time_triggered = DISABLE;             // 禁用时间触发通信
    canInitPara.auto_bus_off_recovery = ENABLE;       // 在检测到离线恢复序列后通过硬件自动恢复
    canInitPara.auto_wake_up = DISABLE;               // 通过软件手动的从睡眠工作模式唤醒 
    canInitPara.auto_retrans = ENABLE;                // 收到发送请求之后,无论是仲裁失败或发送失败, 都会自动重发, 直到发送成功
    canInitPara.rec_fifo_overwrite = DISABLE;         // 0：使能接收FIFO满时覆盖,当接收 FIFO 满时，FIFO 中的数据被新来的数据覆盖
    canInitPara.trans_fifo_order = DISABLE;           // 标识符（Identifier）较小的帧先发送
    canInitPara.working_mode = CAN_NORMAL_MODE;		  // 正常通信模式
    canInitPara.resync_jump_width = CAN_BT_SJW_1TQ;   // 再同步补偿宽度
    canInitPara.time_segment_1 = CAN_BT_BS1_7TQ;      // 位段1  
    canInitPara.time_segment_2 = CAN_BT_BS2_2TQ;      // 位段2
    canInitPara.prescaler = 6;                        // 分频系数，APB1时钟60Mhz，波特率：60 / (6 * (1 + 7 + 2)) = 1Mbps
    can_init(CAN0, &canInitPara);
#if 0	
	canFilterPara.filter_number      = 0;                                        // 过滤器单元编号
	canFilterPara.filter_mode        = CAN_FILTERMODE_MASK;                      // 掩码模式
	canFilterPara.filter_bits        = CAN_FILTERBITS_16BIT;                     // 16位过滤器
	canFilterPara.filter_mask_high   = 0;                                        // 掩码高位
	canFilterPara.filter_mask_low    = 0;                                        // 掩码低位
	canFilterPara.filter_fifo_number = CAN_FIFO1;                                // 关联FIFO
	canFilterPara.filter_enable      = ENABLE;    	
#endif

#if 0	
	canFilterPara.filter_number      = 0;                                        // 过滤器单元编号
	canFilterPara.filter_mode        = CAN_FILTERMODE_LIST;                      // 列表模式
	canFilterPara.filter_bits        = CAN_FILTERBITS_16BIT;                     // 16位过滤器
	canFilterPara.filter_list_high   = (uint16_t)0x5A5 << 5;   					 // 标识符
	canFilterPara.filter_list_low    = (uint16_t)0x5A6 << 5;                     // 标识符
	canFilterPara.filter_mask_high   = (uint16_t)0x5A7 << 5;                     // 标识符
	canFilterPara.filter_mask_low    = (uint16_t)0x5A8 << 5;                     // 标识符
	canFilterPara.filter_fifo_number = CAN_FIFO1;                                // 关联FIFO
	canFilterPara.filter_enable      = ENABLE;  
#endif
	canFilterPara.filter_number      = 0;                                        // 过滤器单元编号
	canFilterPara.filter_mode        = CAN_FILTERMODE_MASK;                      // 掩码模式
	canFilterPara.filter_bits        = CAN_FILTERBITS_16BIT;                     // 16位过滤器
	canFilterPara.filter_list_high   = (uint16_t)0x5A5 << 5;                     // 标识符
	canFilterPara.filter_mask_high   = (uint16_t)0x7FE << 5;                     // 掩码
	
	canFilterPara.filter_list_low    = (uint16_t)0x5A5 << 5;          			 // 标识符 
	canFilterPara.filter_mask_low    = (uint16_t)0x7FE << 5;                     // 掩码
	
	canFilterPara.filter_fifo_number = CAN_FIFO1;                                // 关联FIFO
	canFilterPara.filter_enable      = ENABLE;       

	can_filter_init(&canFilterPara);
	can_interrupt_enable(CAN0, CAN_INT_RFNE1);     // 使能FIFO1非空中断CAN0_RX1_IRQn
	nvic_irq_enable(CAN0_RX1_IRQn, 0, 0);  // 使能CAN中断
}	

void CanbusDrvInit(void)
{
	GpioInit();
	CanInit();
}

static uint8_t g_arrRecvBuf[8];
static uint8_t g_arrTranBuf[8] = {0, 1, 2, 3, 4, 5, 6, 7};
#define TEST_DATA_LEN    8
static bool g_pktRecived = false;

void CAN0_RX1_IRQHandler(void)
{
	can_receive_message_struct canRecvMessage;
	
	can_message_receive(CAN0, CAN_FIFO1, &canRecvMessage);	// 获取CAN邮箱中的数据
	memset(g_arrRecvBuf, 0, sizeof(g_arrRecvBuf));
	memcpy(g_arrRecvBuf, canRecvMessage.rx_data, canRecvMessage.rx_dlen);
	g_pktRecived = true;
}

/**
*******************************************************************
* @function CAN总线发送一帧报文数据
* @param    id,报文帧ID
* @param    buf,数组首地址
* @param    len,要发送的数据个数,不大于8
* @return   
*******************************************************************
*/
bool SendCanFrameData(uint32_t id, uint8_t *buf, uint32_t len)
{
	if (len > 8 || buf == NULL)
	{
		return false;
	}
	
	can_trasnmit_message_struct canTransMessage;
	uint32_t timeout = 0xFFFF;
	uint8_t mailbox = 0;

	canTransMessage.tx_sfid = id;
	canTransMessage.tx_efid = 0x00;
	canTransMessage.tx_ft = CAN_FT_DATA;
	canTransMessage.tx_ff = CAN_FF_STANDARD;
	canTransMessage.tx_dlen = len;
	memcpy(canTransMessage.tx_data, buf, len);
	
	mailbox = can_message_transmit(CAN0, &canTransMessage);

	while ((CAN_TRANSMIT_OK != can_transmit_states(CAN0, mailbox)) && (0 != timeout))
	{
		timeout--;
	}
	if (timeout == 0)
	{
		return false;
	}	
	return true;
}


void CanDrvTest(void)
{
	printf("***************************\n");
	printf("********CAN test begin********\n");
	printf("***************************\n");
	
    if (!SendCanFrameData(0x01, g_arrTranBuf, TEST_DATA_LEN))
	{
		printf("CAN send data error\n");
		return;
	}

	while (!g_pktRecived);
	g_pktRecived = false;
	
	for (uint16_t i = 0; i < TEST_DATA_LEN; i++)
	{
        if (g_arrRecvBuf[i] != g_arrTranBuf[i]){
            printf("0x%02X ", g_arrRecvBuf[i]);
            printf("CAN receive data error\n");
            return;
        }
        printf("0x%02X ", g_arrRecvBuf[i]);
    }
	printf("\n**************************\n");
	printf("********CAN test end*******\n");
	printf("***************************\n");
}
